<template>
  <el-card id="anchorCard"
           :class="'anchor border-radius box-shadow hidden-md-and-down ' + (isFixed ? 'isFixed' : null)"
           :body-style="bodyStyle"
           :style="anchorStyle">
    <el-menu :default-active="active.toString()">
      <el-menu-item v-for="(item, index) in getClassifyDataAndCollect()" @click="scrollTo(index)" :index="(index) + ''"
                    :key="index">
        <span>{{ item.classifyName }}</span>
      </el-menu-item>
    </el-menu>
  </el-card>
</template>

<script setup lang="ts">
const props = defineProps({
  name: {
    type: String,
    default: "Navbar"
  },
  top: {
    type: Number,
    default: 0
  },
  width: {
    type: Number,
    default: 150
  }
});
const {getClassifyDataAndCollect} = useStores.classify();
const active = ref("0");
const isFixed = ref(false);
const targetTop = ref(0);
const bodyStyle = {
  padding: 0
};
const anchorStyle = {
  "--anchor-card-width": props.width + "px",
  "--anchor-card-top": props.top + "px",
};
onMounted(() => {
  if (getClassifyDataAndCollect().length > 0) {
    // 监听页面滚动事件
    window.addEventListener('scroll', handleScroll, false);
    // 获取目标元素与整个网页顶部间的距离
    const el = document.querySelector('#anchorCard') as HTMLElement;
    if (el) {
      targetTop.value = el.getBoundingClientRect().top;
    }
  }
});
onUnmounted(() => {
  // 移除监听器
  window.removeEventListener('scroll', handleScroll);
});
const handleScroll = () => {
  let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
  isFixed.value = scrollTop > targetTop.value;
  for (let i = 0; i < getClassifyDataAndCollect().length; i++) {
    const el = document.querySelector("#" + props.name + i) as HTMLElement;
    if (el && scrollTop - 415 >= el.offsetTop) {
      active.value = i + "";
    }
  }
};
const scrollTo = (index: number) => {
  const el: any = document.querySelector("#" + props.name + index);
  if (!el) {
    return;
  }
  // 获取目标的 offsetTop
  const targetOffsetTop = el.offsetTop + 427;
  // 获取当前 offsetTop
  let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
  // 定义一次跳 10 个像素
  const STEP = 10;
  // 判断是往下滑还是往上滑
  if (scrollTop > targetOffsetTop) {
    // 上滑
    smoothUp();
  } else {
    // 下滑
    smoothDown();
  }

  // 定义往下滑函数
  function smoothDown() {
    // 如果当前 scrollTop 小于 targetOffsetTop 说明视口还没滑到指定位置
    if (scrollTop < targetOffsetTop) {
      // 如果和目标相差距离大于等于 STEP 就跳 STEP
      // 否则直接跳到目标点，目标是为了防止跳过了。
      if (targetOffsetTop - scrollTop >= STEP) {
        scrollTop += STEP;
      } else {
        scrollTop = targetOffsetTop;
      }
      document.body.scrollTop = scrollTop + 1;
      document.documentElement.scrollTop = scrollTop + 1;
      requestAnimationFrame(smoothDown);
    }
  }

  // 定义往上滑函数
  function smoothUp() {
    if (scrollTop > targetOffsetTop) {
      if (scrollTop - targetOffsetTop >= STEP) {
        scrollTop -= STEP;
      } else {
        scrollTop = targetOffsetTop;
      }
      document.body.scrollTop = scrollTop + 1;
      document.documentElement.scrollTop = scrollTop + 1;
      requestAnimationFrame(smoothUp);
    }
  }
}
</script>

<style scoped lang="scss">
.isFixed {
  position: fixed !important;
  top: var(--anchor-card-top) !important;
}

.anchor {
  position: absolute;
  margin-top: 10px;
  margin-right: 600px;
  right: calc(50% + 10px);
  width: var(--anchor-card-width);

  .active {
    color: #409eff;
  }
}

::v-deep(.el-menu) {
  border: none;
}

::v-deep(.el-menu-item) {
  height: 36px;
  line-height: 36px;
  justify-content: center;
}

::v-deep(.el-menu-item.is-active) {
  background-color: #ecf5ff;
}
</style>